# -*- coding:utf8 -*-
import json
import traceback
import os
import re
import requests
import base64
import typing
from lxml import etree
from ..signup.sign_chrome import SignChrome
from scrapy import Request, FormRequest
from .beedancing_cert import BeedancingCert
from squirrel_core.commons.utils.tools import calc_str_md5, upload_file
from squirrel_core.frame.spider_makaka import MakakaSpider

file_path = os.environ.get("FILE_PATH", "/")


class beedancing_score(MakakaSpider):
    name = "beedancing_score"
    header = {
        "Host": "sports.beedancing-timing.com.cn",
        "charset": "utf-8",
        "User-Agent": "Mozilla/5.0 (Linux; Android 12; SM-F926U Build/V417IR; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/101.0.4951.61 Safari/537.36 MMWEBID/346 MicroMessenger/8.0.47.2560(0x28002F36) WeChat/arm64 Weixin Android Tablet NetType/WIFI Language/zh_CN ABI/arm64 MiniProgramEnv/android",
        "Content-Type": "application/json",
        "accept": "*/*"
    }
    serialNumber = ""
    need_ssdbstore_dup = True

    def get_ext_requests_or_urls(self, data=None):
        if data and isinstance(data, str):
            data = json.loads(data)
        if data and isinstance(data, typing.MutableMapping):
            self.serialNumber = data.get("serialNumber", "")
            race_id = data.get("spider_config", {}).get("race_id", "")
            user_id = data.get("spider_config", {}).get("user_id", "")
            race_no = data.get("spider_config", {}).get("race_no", "")
            source_url = data.get("spider_config", {}).get("url", "")
            race_name = data.get("spider_config", {}).get("race_name", "")
            card_num = data.get("spider_config", {}).get("card_num", "")
            if not all([race_id, user_id, race_no, source_url]):
                self.logger.info("参数不全，请仔细核对")
                self.upload_procedure({"serialNumber": self.serialNumber, "code": 101, "message": "参数不全，请仔细核对"})
                self.close_after_idle = True
                self.force_to_close_spider = True
            else:
                self.upload_procedure({"serialNumber": self.serialNumber, "code": 100, "message": "任务启动成功"})
                if "wxxjty.wbs.fit" in source_url:
                    s_no = "".join(re.findall(r"sNo=(.*)", source_url)).strip()
                    yield Request(url=source_url, callback=self.parse_wbs, dont_filter=True, errback=self.err_parse,
                                  meta={"race_id": race_id, "race_no": race_no, "s_no": s_no,
                                        "user_id": user_id, "race_name": race_name, "card_num": card_num})
                else:
                    race_code = int("".join(re.findall(r"id=(\d+)", source_url)))
                    use_proxy = data.get("spider_config", {}).get("use_proxy", True)
                    url = f"https://sports.beedancing-timing.com.cn/api/racecertbyno?race_id={race_code}&cno={race_no}"
                    yield Request(url=url, callback=self.parse, dont_filter=True, errback=self.err_parse, headers=self.header,
                                  meta={"race_id": race_id, "race_code": race_code, "race_no": race_no, "user_id": user_id,
                                        "use_proxy": use_proxy, "race_name": race_name})

    def parse(self, response, **kwargs):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        race_no = response.meta.get("race_no", "")
        race_code = response.meta.get("race_code", "")
        race_name = response.meta.get("race_name", "")
        proxy_url = response.request.meta.get("proxy", "")
        proxy_pre = response.request.meta.get("proxy_pre", "")
        try:
            self.logger.info(f"开始获取race_id:{response.url}")
            content = json.loads(response.text)
            api_data = content.get("data", {})
            if api_data:
                score_dict = api_data.get("score", {})
                i = 0
                cert_url = f"https://sports.beedancing-timing.com.cn/h5/#/pages/index/certquery1?data=%7B%22race_id%22%3A{race_code},%22cno%22%3A%22{race_no}%22%7D"
                while i < 3:
                    try:
                        html = BeedancingCert().get_core(cert_url, proxy_url, proxy_pre)
                        if html:
                            tree = etree.HTML(html)
                            img = tree.xpath("//img[@draggable]/@src")[0].split(",")[1]
                            if img:
                                upload_path = self.download_pic(img, race_id, race_no, user_id)
                                if "武清半程马拉松" in race_name:
                                    if score_dict.get("c05", "") == "男":
                                        sex = 1
                                    elif score_dict.get("c05", "") == "女":
                                        sex = 2
                                    else:
                                        sex = 0
                                    data_dict = {
                                        "raceName": None,
                                        "raceId": race_id,
                                        "raceDate": None,
                                        "itemName": score_dict.get("c03", ""),
                                        "certImg": upload_path,
                                        "raceRoadImg": None,
                                        "name": score_dict.get("c01", ""),
                                        "sex": sex,
                                        "raceNo": score_dict.get("c02", ""),
                                        "pace": score_dict.get("c07", ""),
                                        "speed": None,
                                        "score": score_dict.get("c04", ""),
                                        "shotScore": score_dict.get("c06", ""),
                                        "ranks": {
                                            "allRanks": {
                                                "scoreRank": int(score_dict.get("c17", 0)),
                                                "shotScoreRank": None,
                                                "total": int(score_dict.get("c19", 0))
                                            },
                                            "sexRanks": {
                                                "scoreRank": int(score_dict.get("c18", 0)),
                                                "shotScoreRank": None,
                                                "total": int(score_dict.get("c20", 0))
                                            },
                                            "ageRanks": {
                                                "scoreRank": None,
                                                "shotScoreRank": None,
                                                "total": int(score_dict.get("c22", 0))
                                            }
                                        },
                                        "sectionScore": [
                                            {
                                                "distance": "5km",
                                                "score": score_dict.get("c08", ""),
                                                "pace": score_dict.get("c08", ""),
                                                "rank": None
                                            },
                                            {
                                                "distance": "10km",
                                                "score": score_dict.get("c09", ""),
                                                "pace": score_dict.get("c14", ""),
                                                "rank": None
                                            },
                                            {
                                                "distance": "15km",
                                                "score": score_dict.get("c10", ""),
                                                "pace": score_dict.get("c15", ""),
                                                "rank": None
                                            },
                                            {
                                                "distance": "20km",
                                                "score": score_dict.get("c11", ""),
                                                "pace": score_dict.get("c16", ""),
                                                "rank": None
                                            },
                                            {
                                                "distance": "FINISH",
                                                "score": score_dict.get("c12", ""),
                                                "pace": None,
                                                "rank": None
                                            },
                                        ]
                                    }
                                else:
                                    if score_dict.get("c03", "") == "男":
                                        sex = 1
                                    elif score_dict.get("c03", "") == "女":
                                        sex = 2
                                    else:
                                        sex = 0
                                    data_dict = {
                                        "raceName": None,
                                        "raceId": race_id,
                                        "raceDate": None,
                                        "itemName": None,
                                        "certImg": upload_path,
                                        "raceRoadImg": None,
                                        "name": score_dict.get("c01", ""),
                                        "sex": sex,
                                        "raceNo": score_dict.get("c02", ""),
                                        "pace": score_dict.get("c06", ""),
                                        "speed": float(score_dict.get("c07", 0.0)),
                                        "score": score_dict.get("c05", ""),
                                        "shotScore": score_dict.get("c04", ""),
                                        "ranks": {
                                            "allRanks": {
                                                "scoreRank": int(score_dict.get("c08", 0)),
                                                "shotScoreRank": None,
                                                "total": int(score_dict.get("c09", 0))
                                            },
                                            "sexRanks": {
                                                "scoreRank": int(score_dict.get("c10", 0)),
                                                "shotScoreRank": None,
                                                "total": int(score_dict.get("c11", 0))
                                            },
                                            "ageRanks": {
                                                "scoreRank": int(score_dict.get("c12", 0)),
                                                "shotScoreRank": None,
                                                "total": int(score_dict.get("c13", 0))
                                            }
                                        },
                                        "sectionScore": [
                                            {
                                                "distance": "5km",
                                                "score": score_dict.get("c14", ""),
                                                "pace": score_dict.get("c14", ""),
                                                "rank": None
                                            },
                                            {
                                                "distance": "10km",
                                                "score": score_dict.get("c15", ""),
                                                "pace": score_dict.get("c16", ""),
                                                "rank": None
                                            },
                                            {
                                                "distance": "15km",
                                                "score": score_dict.get("c17", ""),
                                                "pace": score_dict.get("c18", ""),
                                                "rank": None
                                            },
                                            {
                                                "distance": "20km",
                                                "score": score_dict.get("c19", ""),
                                                "pace": score_dict.get("c20", ""),
                                                "rank": ""
                                            },
                                            {
                                                "distance": "半程",
                                                "score": score_dict.get("c21", ""),
                                                "pace": None,
                                                "rank": None
                                            },
                                            {
                                                "distance": "25km",
                                                "score": score_dict.get("c22", ""),
                                                "pace": score_dict.get("c23", ""),
                                                "rank": None
                                            },
                                            {
                                                "distance": "30km",
                                                "score": score_dict.get("c24", ""),
                                                "pace": score_dict.get("c25", ""),
                                                "rank": None
                                            },
                                            {
                                                "distance": "35km",
                                                "score": score_dict.get("c26", ""),
                                                "pace": score_dict.get("c27", ""),
                                                "rank": None
                                            },
                                            {
                                                "distance": "40km",
                                                "score": score_dict.get("c28", ""),
                                                "pace": score_dict.get("c29", ""),
                                                "rank": None
                                            },
                                            {
                                                "distance": "全程",
                                                "score": score_dict.get("c30", ""),
                                                "pace": None,
                                                "rank": None
                                            },
                                        ]
                                    }
                                result_data = {"serialNumber": self.serialNumber, "webType": self.name_first,
                                               "crawlerType": self.name_second, "data": str(data_dict)}
                                result = self.result_item_assembler(response)
                                result['result_data'] = result_data
                                result['_dup_str'] = calc_str_md5(str(data_dict))
                                yield result
                                break
                            else:
                                i += 1
                                proxy_url = self.get_proxy() if self.use_proxy else ""
                        else:
                            i += 1
                            proxy_url = self.get_proxy() if self.use_proxy else ""
                    except:
                        i += 1
                        proxy_url = self.get_proxy() if self.use_proxy else ""
        except Exception:
            self.logger.info(f"获取race_id时出错{response.url}：{traceback.format_exc()}")

    def parse_wbs(self, response):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        race_no = response.meta.get("race_no", "")
        race_name = response.meta.get("race_name", "")
        s_no = response.meta.get("s_no", "")
        card_num = response.meta.get("card_num", "")
        try:
            self.logger.info("开始获取赛事名称")
            r_name = response.xpath("//span[@id='ssmc']/text()").extract_first()
            url = "https://wxxjty.wbs.fit/index/index/checkCertExists"
            header = {
                "Host": "wxxjty.wbs.fit",
                "Accept": "*/*",
                "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
                "X-Requested-With": "XMLHttpRequest",
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"
            }
            post_data = {"sNo": s_no, "haoma": card_num, "sfz": "", "xm": ""}
            yield FormRequest(url, callback=self.parse_wbs_score, formdata=post_data, headers=header,
                              dont_filter=True, errback=self.err_parse, meta={"r_name": r_name, "race_id": race_id, "race_name": race_name,
                                                                              "race_no": race_no, "user_id": user_id})
        except Exception as e:
            self.logger.info(f"获取赛事名称出错：{e}")

    def parse_wbs_score(self, response):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        race_no = response.meta.get("race_no", "")
        r_name = response.meta.get("r_name", "")
        race_name = response.meta.get("race_name", "")
        try:
            self.logger.info(f"开始获取{race_no}的成绩")
            zs_id = json.loads(response.text).get("zsID", "")
            url = f"https://wxxjty.wbs.fit/management/zs/getPrintView?SN={zs_id}"
            yield Request(url=url, callback=self.parse_wbs_cert, dont_filter=True, errback=self.err_parse,
                          meta={"race_id": race_id, "race_no": race_no, "zs_id": zs_id,
                                "user_id": user_id, "r_name": r_name, "race_name": race_name})
        except Exception as e:
            self.logger.info(f"获取{race_no}的成绩出错：{e}")

    def parse_wbs_cert(self, response):
        race_id = response.meta.get("race_id", "")
        user_id = response.meta.get("user_id", "")
        race_no = response.meta.get("race_no", "")
        r_name = response.meta.get("r_name", "")
        zs_id = response.meta.get("zs_id", "")
        race_name = response.meta.get("race_name", "")
        proxy_url = response.request.meta.get("proxy", "")
        proxy_pre = response.request.meta.get("proxy_pre", "")
        try:
            self.logger.info(f"开始获取{race_no}的成绩")
            name = "".join(response.xpath("//div[@id='u3']//text()").extract()).strip()
            bib = "".join(response.xpath("//div[@id='u5']//text()").extract()).strip()
            group = "".join(response.xpath("//div[@id='u7']//text()").extract()).strip()
            shot_score = "".join(response.xpath("//div[@id='u11']//text()").extract()).strip()

            pace = "".join(response.xpath("//div[@id='u13']//text()").extract()).strip()
            score = "".join(response.xpath("//div[@id='u19']//text()").extract()).strip()
            score_data = {"race_name": race_name, "itemName": group, "name": name, "raceNo": bib, "pace": pace,
                          "speed": "", "distance": "", "shotScore": shot_score, "score": score}
            i = 0
            url = f"https://wxxjty.wbs.fit/index/index/getSaishiCerti?zsID={zs_id}&ssmc={r_name}"
            while i < 3:
                try:
                    img_base64 = SignChrome().get_pic2(url, proxy_url, proxy_pre)
                    if "data:image" in img_base64:
                        image_data = img_base64.split(",", 1)[1]
                        upload_path = self.download_pic(image_data, race_id, race_no, user_id)
                        score_data["certImg"] = upload_path
                        result_data = {"serialNumber": self.serialNumber, "webType": self.name_first,
                                       "crawlerType": self.name_second, "data": str(score_data)}
                        result = self.result_item_assembler(response)
                        result['result_data'] = result_data
                        yield result
                        break
                    else:
                        i += 1
                        proxy_url = self.get_proxy() if self.use_proxy else ""
                except:
                    i += 1
                    proxy_url = self.get_proxy() if self.use_proxy else ""
        except Exception as e:
            self.logger.info(f"获取{race_no}的成绩出错：{e}")

    def download_pic(self, img, race_id, race_no, user_id):
        try:
            self.logger.info(f"开始下载图片")
            pic_name = f"{race_id}_{race_no}.jpg"
            dir_path = os.path.join(file_path, self.name_first)
            if not os.path.exists(dir_path):
                os.makedirs(dir_path)
            save_path = os.path.join(dir_path, pic_name)
            if not os.path.exists(save_path):
                img_data = base64.b64decode(img.encode("utf-8"))
                with open(save_path, "wb") as f:
                    f.write(img_data)
                upload_path = f"flow/{race_id}/{user_id}/pic/{pic_name}"
                upload_flag = upload_file(save_path, upload_path)
                if upload_flag:
                    self.logger.info(f"{save_path}上传成功：{upload_path}")
                else:
                    self.logger.info(f"{save_path}上传失败：{upload_path}")
                return upload_path
        except Exception:
            self.logger.error(f"下载图片失败：{traceback.format_exc()}")
            return ""

    def err_parse(self, failure):
        self.logger.warning(f"请求失败：{failure.request.url},错误原因:{traceback.format_exc()}")

    def get_proxy(self):
        url = "http://api.dmdaili.com/dmgetip.asp?apikey=062c68ee&pwd=2ceacf762585db3e1d24cbdb4ef11091&getnum=1&httptype=1&geshi=2&fenge=&fengefu=&operate=all"
        content = requests.get(url).text
        ip = json.loads(content).get("data", [])[0].get("ip", "")
        port = json.loads(content).get("data", [])[0].get("port", "")
        proxy = f"http://{ip}:{port}"
        return proxy
